# -*- coding: utf-8 -*-
# @Time    : 2024/7/10 09:51
# @Author  : yujiahao
# @File    : 10_fastapi_request_body_nested_model.py
# @description:请求体 - 嵌套模型 使用 FastAPI，可以定义、校验、记录文档并使用任意深度嵌套的模型（归功于Pydantic）。


from typing import List, Union, Set

from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl

app = FastAPI()


# todo 1、list
class Item(BaseModel):
    '''
    1、声明具有子类型的 List(3.9以下都是大写的L )
    2、要声明具有子类型的类型，例如 list、dict、tuple：
    3、从 typing 模块导入它们
    4、使用方括号 [ 和 ] 将子类型作为「类型参数」传入
    5、完全和python相同的标准语法，可以声明元素的类型
    '''
    name: str
    description: Union[str, None] = None
    price: float
    #
    tax: Union[float, None] = None
    tags: list[int] = []


# todo 2、set
# 同理，这个会去重
# todo 3、特殊的类型和校验
# 除了普通的单一值类型（如 str、int、float 等）外，你还可以使用从 str 继承的更复杂的单一值类型。
# 例如下面可以把url声明为 Pydantic 的 HttpUrl，而不是 str
# 该字符串将被检查是否为有效的 URL，并在 JSON Schema / OpenAPI 文档中进行记录。
class Yujiacun(BaseModel):
    name: str
    trees: set[int] = set()
    url: HttpUrl


#  todo 4、嵌套模型
# ① 将上面的模型用做本类的子模型
# ② 将子模型用作类型

class Beirencun(BaseModel):
    name: str
    ranges: List[int] = []
    yujia: Yujiacun
    village: Yujiacun | None = None
    # todo 5、深度嵌套模型
    hhh: list[Yujiacun] | None = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, yujiacun: Yujiacun, beirencun: Beirencun):
    results = {"item_id": item_id, "item": item, "yujiacun": yujiacun, "beirencun": beirencun}
    return results


# todo 6、纯列表请求体

# 如果你期望的 JSON 请求体的最外层是一个 JSON array（即 Python list），则可以在路径操作函数的参数中声明此类型，
# 就像声明 Pydantic 模型一样： images: List[Image]


@app.post("/images/multiple/")
async def create_multiple_images(images: list[Yujiacun]):
    return images


# todo 7、任意 dict 构成的请求体


@app.post("/index-weights/")
async def create_index_weights(weights: dict[int, float]):
    '''这里key类型虽然是整数，但是输入的时候key还是要带双引号的， Pydantic 具有自动转换数据的功能。

    {
      "1": 1.2,
      "2": 2.3,
      "3": 3.4
    }
    '''
    return weights
